/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.beautycenter.ModelosTabela;

import br.com.beautycenter.Funcionalidades.Data;
import br.com.beautycenter.DAO.PersisteCliente;
import br.com.beautycenter.DAO.PersistePrestacao;
import br.com.beautycenter.DAO.PersisteRecebimentoExtra;
import br.com.beautycenter.DAO.PersisteVenda;
import br.com.beautycenter.Funcionalidades.Validacoes;
import br.com.beautycenter.bean.Cliente;
import br.com.beautycenter.bean.Prestacao;
import br.com.beautycenter.bean.RecebimentoExtraCaixa;
import br.com.beautycenter.bean.Venda;
import br.com.beautycenter.view.ConfirmarPagamento;
import java.text.ParseException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.table.AbstractTableModel;
import org.joda.time.DateTime;

/**
 *
 * @author magelinha
 */
public class TableModelConfirmarVenda extends AbstractTableModel {
    
    private List<Prestacao> listaPrestacoes;
    PersisteCliente persisteCliente = new PersisteCliente();
    PersistePrestacao persistePrestacao = new PersistePrestacao();
    PersisteVenda persisteVenda = new PersisteVenda();
    PersisteRecebimentoExtra persisteRecebimento = new PersisteRecebimentoExtra();
    
    Cliente cliente;
    
    ConfirmarPagamento parent;
    private String[] colunas = new String[]{"*", "Vencimento", "Valor"};
    
    private static final int SELECIONAR = 0;
    private static final int DATA = 1;
    private static final int VALOR = 2;

    public Cliente getCliente() {
        return cliente;
    }

    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }
    
    public TableModelConfirmarVenda(JFrame parent, List<Prestacao> listaPrestacaoes) {
        this.listaPrestacoes = listaPrestacaoes;
        this.parent = (ConfirmarPagamento)parent;
    }

    @Override
    public int getRowCount() {
        return listaPrestacoes.size();
    }

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public Object getValueAt(final int rowIndex, int columnIndex) {
        switch(columnIndex){
            case SELECIONAR:
                return listaPrestacoes.get(rowIndex).isSelecionado();
                
            case DATA:
                return Data.formatoDataConvencional.format(listaPrestacoes.get(rowIndex).getDataPagamento());
                
            case VALOR:
                return Validacoes.formatoMoeda.format(listaPrestacoes.get(rowIndex).getValor());
                
            default:
                throw new IndexOutOfBoundsException("Não é possivel pegar o valor da coluna desejada");
        }
    }
    
    @Override
    public String getColumnName(int columnIndex){
        return colunas[columnIndex];
    }
    
    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex){
        Prestacao prestacao = listaPrestacoes.get(rowIndex);
        switch(columnIndex){
            case SELECIONAR:
                prestacao.setSelecionado((Boolean)aValue);
                break;
            
            case DATA:
                try {
                    Date data = Data.formatoDataConvencional.parse(aValue.toString());
                    prestacao.setDataPagamento(data);
                } catch (ParseException ex) {
                    prestacao.setDataPagamento(null);
                }
                break;
            
            case VALOR:
                prestacao.setValor((Double)aValue);
                break;
                
            default:
                throw new IndexOutOfBoundsException("Não é possivel pegar o valor da coluna desejada");
        }
        
        fireTableCellUpdated(rowIndex, columnIndex); // Notifica a atualização da célula
    }
    
    
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex){
        if(columnIndex == SELECIONAR) return true;
        return false;
    }
    
    @Override
    public Class<?> getColumnClass(int columnIndex){
        switch(columnIndex){
            case SELECIONAR:
                return Boolean.class;
                
            case DATA:
                return String.class;
                
            case VALOR:
                return String.class;
                
            default:
                throw new IndexOutOfBoundsException("Coluna não existe na tabela " + columnIndex);
        }
    }
    
    /*
     * Metodos para manipulação de dados
     */
    
    /**
     * Pega a sessão selecionada na tabela
     * @param linha 
     */
    public Prestacao getPrestacao(int linha){
        return listaPrestacoes.get(linha);
    }
    
    public void addPrestacao(Prestacao prestacao){
        listaPrestacoes.add(prestacao);
        
        int ultimo = getRowCount()-1;
        
        fireTableRowsInserted(ultimo, ultimo);
    }
    
    /**
     * Remove uma determinada linha da tabela
     */
    public void removePrestacao(int linha){
        listaPrestacoes.remove(linha);
        
        fireTableRowsDeleted(linha, linha);
    }
    
    public void addListaPrestacaoes(List<Prestacao> lista){
        int indice = getRowCount();
        listaPrestacoes.addAll(lista);
        
        fireTableRowsInserted(indice, indice + lista.size());
    }
    
    public void clear(){
        listaPrestacoes.clear();
        fireTableDataChanged();
    }
    
    //seleciona todos na tabela
    public void selecionarTodos(){
        for(Prestacao item: listaPrestacoes){
            item.setSelecionado(true);
        }
        
        fireTableDataChanged();
    }
    
    //desmarca todos na tabela
    public void desmarcarTodos(){
        for(Prestacao item: listaPrestacoes){
            item.setSelecionado(false);
        }
        
        fireTableDataChanged();
    }
    
    /**
     * Remevo os que estão marcados na tabela
     */
    public void removerSelecionados(){
        Iterator<Prestacao> it = listaPrestacoes.iterator();
        
        while(it.hasNext()){
            Prestacao prestacao = it.next();
            if(prestacao.isSelecionado()) {
                it.remove();
            }
        }
        
        fireTableDataChanged();
    }
    
    /**
     * Pega todos que estão selecionados e faz o somatorio
     * @return 
     */
    public double somatorioSelecionado(){
        double soma = 0;
        for(Prestacao item: listaPrestacoes){
            if(item.isSelecionado()) soma += item.getValor();
        }
        
        return soma;
    }
    
    public void redefinirPrestacoes(Double totalRecebido){
        Double total = new Double(totalRecebido.doubleValue());
        for(Prestacao item: listaPrestacoes){
            //se a prestação ta marcada, então quita totalmente ou parte dela. Faz isso até que valor recebido seja 0
            if(item.isSelecionado()){
                /**
                 * Verifica se o valor da prestação é maior que o valor recebido. Caso seja, altera o valor da
                 * prestação para o valor recebido e cria um nova prestação com o resto que falta pra pagar
                 * 
                 * ex.: 
                 *      Prestação: 100,00
                 *      Valor Recebido: 20,00
                 * 
                 * Prestação Paga: 20,00 ----- confirmarRecebimento(true)   ----- Vencimento (x/x/x)
                 * Nova Prestação: 80,00 ----- confirmarRecebimento(false)  ----- Vencimento (x/x+1/x) - 1 mês depois
                 */
                
                if(item.getValor() > totalRecebido){
                    //adiciona 1 mês na data de pagamento
                    DateTime atual = new DateTime(item.getDataPagamento().getTime());
                    DateTime base = atual.plusMonths(1);
                    
                    Prestacao aux = new Prestacao(); //cria a nova prestação
                    aux.setIdPrestacao(0); //segurança
                    aux.setDataPagamento(base.toDate()); //data de pagamento para 1 mês depois
                    aux.setValor(item.getValor() - totalRecebido); //novo valor de pagamento
                    aux.setConfirmarRecebimento(false); //não confirma o recebimento
                    aux.setVenda(item.getVenda()); //joga a prestação para a venda da prestação a ser confirmada o recebimento
                    persistePrestacao.salvar(aux);
                    
                    cliente.setCredito(cliente.getCredito() - aux.getValor());
                    
                    //altera o valor da prestação para o valor recebido e quita a prestação
                    item.setValor(totalRecebido);
                    item.setConfirmarRecebimento(true);
                    item.setRecebimentoExtra(true);
                    item.setDataPagamento(new Date());
                    
                    persistePrestacao.atualizar(item);
                    cliente.setCredito(cliente.getCredito() + item.getValor());
                    
                    break;
                }else if(item.getValor() == totalRecebido){
                    //Se o totalRecebido for igual o valor da prestação, apenas quita a prestação
                    item.setConfirmarRecebimento(true);
                    item.setDataPagamento(new Date());
                    item.setRecebimentoExtra(true);
                    persistePrestacao.atualizar(item);
                    
                    cliente.setCredito(cliente.getCredito() + item.getValor());
                    break;
                    
                }else{
                    //se o valor recebido for maior que a prestação, apenas quita e cria um novo valor recebido
                    item.setConfirmarRecebimento(true);
                    item.setDataPagamento(new Date());
                    item.setRecebimentoExtra(true);
                    persistePrestacao.atualizar(item);
                    
                    cliente.setCredito(cliente.getCredito() + item.getValor());
                    
                    totalRecebido -= item.getValor();
                    
                    //volta pro for até que entre no primeiro if ou no else if
                }
                
                if(totalRecebido.intValue() == 0) break;
            }
        }
        
        persisteCliente.atualizar(cliente);
        RecebimentoExtraCaixa recebimento = new RecebimentoExtraCaixa();
        recebimento.setIdRecebimentoExtraCaixa(0);
        recebimento.setDtCadastro(new Date());
        recebimento.setValorRecebimento(total);
        recebimento.setCliente(cliente);
        
        persisteRecebimento.salvar(recebimento);
    }
    
    public void corrigirNumeroPrestacao(){
        for(Venda item: persisteVenda.retornarVendasPorCliente(cliente)){
            List<Prestacao> temp = item.getListaPrestacoes();
            Collections.sort(temp, new Comparator<Prestacao>() {
                //ordena a lista de prestações pela datas
                @Override
                public int compare(Prestacao o1, Prestacao o2) {
                    DateTime t1 = new DateTime(o1.getDataPagamento().getTime());
                    DateTime t2 = new DateTime(o2.getDataPagamento().getTime());
                    
                    t1 = new DateTime(t1.getYear(), t1.getMonthOfYear(), t1.getDayOfMonth(), 0, 0, 0);
                    t2 = new DateTime(t2.getYear(), t2.getMonthOfYear(), t2.getDayOfMonth(), 0, 0, 0);
                    
                    
                    return t1.compareTo(t2);
                }
            });
            
            //insere o numero da prestação
            int aux = 1;
            for(Prestacao subItem: temp){
                subItem.setNumeroPrestacao(aux);
                aux++;
                
                persistePrestacao.atualizar(subItem);
            }
        }    
    }
    
    public void quitarPrestacoes(){
        double total = 0.0;
        for(Prestacao item: listaPrestacoes){
            if(item.isSelecionado()){
                item.setConfirmarRecebimento(true);
                item.setRecebimentoExtra(true);
                item.setDataPagamento(new Date());
                persistePrestacao.atualizar(item);
                cliente.setCredito(cliente.getCredito() + item.getValor());
                total += item.getValor();
            }
        }
        
        persisteCliente.atualizar(cliente);
        
        RecebimentoExtraCaixa recebimento = new RecebimentoExtraCaixa();
        recebimento.setIdRecebimentoExtraCaixa(0);
        recebimento.setDtCadastro(new Date());
        recebimento.setValorRecebimento(total);
        recebimento.setCliente(cliente);
        
        persisteRecebimento.salvar(recebimento);
    }
    
    
    
}
